package com.ksd.utils;

import com.ksd.exception.ApiException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.Base64Utils;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.SecureRandom;

/**
 * 加密解密工具类
 */
@Slf4j
public class EncryptDecryptData {


    /**
     * AES 加密工具默认参数
     */
    private static final String DEFAULT_AES_CIPHER_ALGORITHM = "AES/CBC/PKCS5Padding";
    private static final String DEFAULT_AES_EXCHANGE_PASSWORD = "dGMtb2ZhLXVzZXJj";
    private static final byte[] DEFAULT_AES_DEVIATION_VALUE = "0000000000000000".getBytes(StandardCharsets.UTF_8);


    /**
     * DES加密
     *
     * @param password 密码
     * @param key      密钥
     */
    public static String encryptByDes(byte[] password, String key) {
        try {
            SecureRandom random = new SecureRandom();
            //使用密钥，创建一个密钥描述符
            DESKeySpec desKeySpec = new DESKeySpec(key.getBytes());
            //创建一个密匙工厂，然后用它把 dESKeySpec 密钥描述符实例转换成密钥
            SecretKeyFactory secretKeyFactory = SecretKeyFactory.getInstance("DES");
            SecretKey secretKey = secretKeyFactory.generateSecret(desKeySpec);

            //Cipher对象实际完成加密操作
            Cipher cipher = Cipher.getInstance("DES");
            //用密匙初始化Cipher对象
            cipher.init(Cipher.ENCRYPT_MODE, secretKey, random);
            //正式执行加密操作
            return Base64Utils.encodeToString(cipher.doFinal(password));
        } catch (Throwable e) {
            e.printStackTrace();
            throw new ApiException("DES加密出现异常");
        }
    }


    /**
     * DES解密
     *
     * @param desPasswd 密码
     * @param key       密钥
     */
    public static String decryptByDes(String desPasswd, String key){
        String s = null;
        try {
            // DES算法要求有一个可信任的随机数源
            SecureRandom random = new SecureRandom();
            // 创建一个 DESKeySpec 密钥描述符对象
            DESKeySpec desKeySpec = new DESKeySpec(key.getBytes());
            // 创建一个密匙工厂
            SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
            // 将DESKeySpec对象转换成SecretKey对象
            SecretKey secretKey = keyFactory.generateSecret(desKeySpec);
            // Cipher对象实际完成解密操作
            Cipher cipher = Cipher.getInstance("DES");
            // 用密匙初始化Cipher对象
            cipher.init(Cipher.DECRYPT_MODE, secretKey, random);
            // 真正开始解密操作
            s = new String(cipher.doFinal(Base64Utils.decodeFromString(desPasswd)));
        } catch (Exception e) {
            e.printStackTrace();
            throw new ApiException("DES解密出现异常");
        }
        return s;
    }







	/**
	 * AES加密
	 *
	 * @param content  原文
	 * @return base64.encode(密文)
	 */
	public static String encryptByAes(String content) {
		return EncryptDecryptData.encryptByAes(content, DEFAULT_AES_EXCHANGE_PASSWORD);
	}
    /**
     * AES加密
     *
     * @param content  原文
     * @param password 密钥
     * @return base64.encode(密文)
     */
    public static String encryptByAes(String content, String password) {
        try {
            // 生成密钥，支持 AES 或 Rijndael
            SecretKeySpec secretKey = new SecretKeySpec(password.getBytes(StandardCharsets.UTF_8), "AES");
            // 新建加密器，加密模式为 AES/CBC/PKCS5Padding
            Cipher cipher = Cipher.getInstance(DEFAULT_AES_CIPHER_ALGORITHM);
            // 设置偏移量为 16 个 0
            IvParameterSpec iv = new IvParameterSpec(DEFAULT_AES_DEVIATION_VALUE);
            // 将配置好的参数传递给加密器
            cipher.init(Cipher.ENCRYPT_MODE, secretKey, iv);
            // 用加密器加密传入的明文
            byte[] encrypted = cipher.doFinal(content.getBytes(StandardCharsets.UTF_8));
            // 返回密文的base64结果
            return Base64Utils.encodeToString(encrypted);
        } catch (Exception error) {
            log.error("AES加密数据失败: " + error.getMessage());
            throw new ApiException("AES加密出现异常");
        }
    }



	/**
	 * AES解密
	 *
	 * @param content  base64.encode(密文)
	 * @return 明文
	 */
	public static String decryptByAes(String content) {
		return EncryptDecryptData.decryptByAes(content, DEFAULT_AES_EXCHANGE_PASSWORD);
	}
    /**
     * AES解密
     *
     * @param content  base64.encode(密文)
     * @param password 密钥
     * @return 明文
     */
    public static String decryptByAes(String content, String password) {
        try {
            // 生成密钥，支持 AES 或 Rijndael
            SecretKeySpec secretKey = new SecretKeySpec(password.getBytes(StandardCharsets.UTF_8), "AES");
            // 新建加密器，加密模式为 AES/CBC/PKCS5Padding
            Cipher cipher = Cipher.getInstance(DEFAULT_AES_CIPHER_ALGORITHM);
            // 设置偏移量为 16 个 0
            IvParameterSpec iv = new IvParameterSpec(DEFAULT_AES_DEVIATION_VALUE);
            // 将配置好的参数传递给加密器
            cipher.init(Cipher.DECRYPT_MODE, secretKey, iv);
            // 返回密文的解密内容（先由base64解码）
            return new String(cipher.doFinal(Base64Utils.decode(content.getBytes(StandardCharsets.UTF_8))));
        } catch (Exception error) {
            log.error("AES解密数据失败: " + error.getMessage());
            throw new ApiException("AES解密出现异常");
        }
    }




    public static void main(String args[]) {

		//System.out.println("================ DES 加解密测试开始 ================");
        //try {
        //    String originContent = "123456";
        //    byte[] passwd = originContent.getBytes();
        //    System.out.println("加密前,原文:" + originContent + "  密钥:"+DES_KEY);
        //    String desPasswd = encryptByDes(passwd, DES_KEY);
        //    System.out.println("加密后:" + desPasswd);
        //    String decPasswd = decryptByDes(desPasswd, DES_KEY);
        //    System.out.println("解密后:" + decPasswd);
        //} catch (Exception e) {
        //    e.printStackTrace();
        //}
		//System.out.println("================ DES 加解密测试结束 ================\n");
        //
        //
        //
		System.out.println("================ AES/CBC/PKCS5Padding 加解密测试开始 ================");
        System.out.println("使用密钥: " + DEFAULT_AES_EXCHANGE_PASSWORD);
        String originContent = "123456";
        System.out.println("加密前，原文:" + originContent);
        String encryptContent = EncryptDecryptData.encryptByAes(originContent);
        String decryptContent = EncryptDecryptData.decryptByAes(encryptContent, DEFAULT_AES_EXCHANGE_PASSWORD);
        System.out.println("密文(base64):" + encryptContent);
        //System.out.println("密文(base64)解密:" + decryptContent);
        //System.out.println("================ AES/CBC/PKCS5Padding 加解密测试结束 ================");
    }
}
